﻿///////////////////////////////////////////////////////////////////////////////
//
// This file is part of the BassDrop project
//   https://code.google.com/p/bass-drop/
//
//
// Creator:	Gergely Krajcsovszki (krajcsovszkig@hotmail.com)
// Date:	2014-04-20 18:45
//
//
// Copyright © 2013-2014. Gergely Krajcsovszki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BassDrop.Core.Common.Data.IO.Data
{
	/// <summary>
	/// Class for hash codes computed from files. Specifies the code
	/// and the algorithm used for creating it
	/// </summary>
	public class Hash : IEquatable<Hash>
	{
		/// <summary>
		/// The hash code of the file. Use a base64-encoded version of it
		/// if it isn't a string by default
		/// </summary>
		public string HashCode
		{
			get;
			private set;
		}

		/// <summary>
		/// The standard name of the algorithm used to create the hash, eg. "md5"
		/// </summary>
		public string Algorithm // TODO: ez legyen valami enum
		{
			get;
			private set;
		}

		/// <summary>
		/// Create a new hash object
		/// </summary>
		/// <param name="hashCode">The hash code of the file. Use a base64-encoded version of it if it isn't a string by default</param>
		/// <param name="algorithm">The standard name of the algorithm used to create the hash, eg. "md5"</param>
		public Hash( string hashCode, string algorithm )
		{
			HashCode = hashCode;
			Algorithm = algorithm;
		}

		#region IEquatable<Hash> Members

		/// <summary>
		/// Indicates whether the current object is equal to another object of the same type.
		/// </summary>
		/// <param name="other">An object to compare with this object.</param>
		/// <returns>true if the current object is equal to the other parameter; otherwise, false.</returns>
		public bool Equals( Hash other )
		{
			if ( (object) other == null )
			{
				return false;
			}

			return other.Algorithm == Algorithm && other.HashCode == HashCode;
		}

		#endregion

		/// <summary>
		/// Determines whether the specified object is equal to the current object.
		/// </summary>
		/// <param name="obj">An object to compare with this object.</param>
		/// <returns>true if the current object is equal to the other parameter; otherwise, false.</returns>
		public override bool Equals( object obj )
		{
			return Equals( obj as Hash );
		}

		/// <summary>
		/// Serves as the default hash function.
		/// </summary>
		/// <returns>A hash code for the current object.</returns>
		public override int GetHashCode()
		{
			unchecked
			{
				int hash = 17;

				hash = hash * 23 + Algorithm.GetHashCode();
				hash = hash * 23 + HashCode.GetHashCode();

				return hash;
			}
		}

		/// <summary>
		/// Returns whether v1 equals v2
		/// </summary>
		/// <param name="h1"></param>
		/// <param name="h2"></param>
		/// <returns></returns>
		public static bool operator ==( Hash h1, Hash h2 )
		{
			if ( System.Object.ReferenceEquals( h1, h2 ) )
			{
				return true;
			}

			if ( ((object) h1 == null) || ((object) h2 == null) )
			{
				return false;
			}

			return h1.Equals( h2 );
		}

		/// <summary>
		/// Returns whether v1 does not equal v2
		/// </summary>
		/// <param name="h1"></param>
		/// <param name="h2"></param>
		/// <returns></returns>
		public static bool operator !=( Hash h1, Hash h2 )
		{
			return !(h1 == h2);
		}
	}
}
